package org.chen.flight.service;

import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.chen.common.flight.*;
import org.chen.common.flight.request.FlightSearchRequest;
import org.chen.common.flight.response.OneWayFlightSearchResponse;
import org.chen.common.flight.response.RoundTripFlightSearchResponse;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.stereotype.Service;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.List;

@Service
@Slf4j
public class ExcelExportService {
    /**
     * 导出单程航班数据到Excel
     */
    public ByteArrayResource exportOneWayToExcel(OneWayFlightSearchResponse response,
                                                 FlightSearchRequest request,
                                                 boolean exportLowestPriceOnly) {
        try (Workbook workbook = new XSSFWorkbook()) {
            Sheet sheet = workbook.createSheet("单程航班数据");

            // 创建样式
            CellStyle headerStyle = createHeaderStyle(workbook);
            CellStyle dataStyle = createDataStyle(workbook);
            CellStyle priceStyle = createPriceStyle(workbook);

            // 创建标题行
            createOneWayHeaderRow(sheet, headerStyle);

            // 处理数据
            List<OneWayFlightInfo> flights = response.getFlights();
            if (exportLowestPriceOnly && !flights.isEmpty()) {
                flights = flights.subList(0, Math.min(1, flights.size()));
            }

            // 填充数据
            fillOneWayDataRows(sheet, flights, dataStyle, priceStyle);

            // 调整列宽
            adjustOneWayColumnWidths(sheet);

            // 转换为字节数组
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            workbook.write(outputStream);

            log.info("单程航班Excel导出完成，数据行数: {}", flights.size());
            return new ByteArrayResource(outputStream.toByteArray());

        } catch (IOException e) {
            log.error("导出单程航班Excel失败", e);
            throw new RuntimeException("导出Excel失败", e);
        }
    }

    /**
     * 导出往返航班数据到Excel
     */
    public ByteArrayResource exportRoundTripToExcel(RoundTripFlightSearchResponse response,
                                                    FlightSearchRequest request,
                                                    boolean exportLowestPriceOnly) {
        try (Workbook workbook = new XSSFWorkbook()) {
            Sheet sheet = workbook.createSheet("往返航班数据");

            // 创建样式
            CellStyle headerStyle = createHeaderStyle(workbook);
            CellStyle dataStyle = createDataStyle(workbook);
            CellStyle priceStyle = createPriceStyle(workbook);

            // 创建标题行
            createRoundTripHeaderRow(sheet, headerStyle);

            // 处理数据
            List<RoundTripFlightInfo> flights = response.getFlights();
            if (exportLowestPriceOnly && !flights.isEmpty()) {
                flights = flights.subList(0, Math.min(1, flights.size()));
            }

            // 填充数据
            fillRoundTripDataRows(sheet, flights, dataStyle, priceStyle);

            // 调整列宽
            adjustRoundTripColumnWidths(sheet);

            // 转换为字节数组
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            workbook.write(outputStream);

            log.info("往返航班Excel导出完成，数据行数: {}", flights.size());
            return new ByteArrayResource(outputStream.toByteArray());

        } catch (IOException e) {
            log.error("导出往返航班Excel失败", e);
            throw new RuntimeException("导出Excel失败", e);
        }
    }

    /**
     * 创建单程航班表头
     */
    private void createOneWayHeaderRow(Sheet sheet, CellStyle headerStyle) {
        Row headerRow = sheet.createRow(0);
        String[] headers = {
                "航班号", "航空公司", "出发时间", "到达时间", "飞行时长", "跨天数",
                "出发机场", "到达机场", "出发城市", "到达城市", "出发航站楼", "到达航站楼",
                "成人价格", "成人税费", "成人总价", "儿童价格", "儿童税费", "儿童总价",
                "婴儿价格", "婴儿税费", "婴儿总价", "币种", "舱位等级", "中转次数",
                "是否直飞", "行李额度", "痛苦指数", "票数", "购买须知"
        };

        for (int i = 0; i < headers.length; i++) {
            Cell cell = headerRow.createCell(i);
            cell.setCellValue(headers[i]);
            cell.setCellStyle(headerStyle);
        }
    }

    /**
     * 创建往返航班表头
     */
    private void createRoundTripHeaderRow(Sheet sheet, CellStyle headerStyle) {
        Row headerRow = sheet.createRow(0);
        String[] headers = {
                "路线描述", "成人总价", "儿童总价", "婴儿总价", "币种", "舱位等级",
                "总中转次数", "是否全程直飞", "行李额度", "痛苦指数", "票数",
                // 去程信息
                "去程航班号", "去程出发时间", "去程到达时间", "去程飞行时长", "去程中转次数", "去程是否直飞",
                "去程出发机场", "去程到达机场", "去程出发城市", "去程到达城市",
                // 返程信息
                "返程航班号", "返程出发时间", "返程到达时间", "返程飞行时长", "返程中转次数", "返程是否直飞",
                "返程出发机场", "返程到达机场", "返程出发城市", "返程到达城市",
                "购买须知"
        };

        for (int i = 0; i < headers.length; i++) {
            Cell cell = headerRow.createCell(i);
            cell.setCellValue(headers[i]);
            cell.setCellStyle(headerStyle);
        }
    }

    /**
     * 填充单程数据行
     */
    private void fillOneWayDataRows(Sheet sheet, List<OneWayFlightInfo> flights,
                                    CellStyle dataStyle, CellStyle priceStyle) {
        for (int i = 0; i < flights.size(); i++) {
            Row row = sheet.createRow(i + 1);
            OneWayFlightInfo flight = flights.get(i);
            int cellIndex = 0;

            // 基础信息
            setCellValue(row, cellIndex++, flight.getFlightNumber(), dataStyle);
            setCellValue(row, cellIndex++, flight.getAirline(), dataStyle);
            setCellValue(row, cellIndex++, flight.getDepartureTime(), dataStyle);
            setCellValue(row, cellIndex++, flight.getArrivalTime(), dataStyle);
            setCellValue(row, cellIndex++, flight.getDuration(), dataStyle);
            setCellValue(row, cellIndex++, flight.getCrossDays(), dataStyle);

            // 机场信息
            setCellValue(row, cellIndex++, flight.getDepartureAirport(), dataStyle);
            setCellValue(row, cellIndex++, flight.getArrivalAirport(), dataStyle);
            setCellValue(row, cellIndex++, flight.getDepartureCity(), dataStyle);
            setCellValue(row, cellIndex++, flight.getArrivalCity(), dataStyle);
            setCellValue(row, cellIndex++, flight.getDepartureTerminal(), dataStyle);
            setCellValue(row, cellIndex++, flight.getArrivalTerminal(), dataStyle);

            // 价格信息
            setCellValue(row, cellIndex++, flight.getAdultPrice(), priceStyle);
            setCellValue(row, cellIndex++, flight.getAdultTax(), priceStyle);
            setCellValue(row, cellIndex++, flight.getAdultTotalPrice(), priceStyle);
            setCellValue(row, cellIndex++, flight.getChildPrice(), priceStyle);
            setCellValue(row, cellIndex++, flight.getChildTax(), priceStyle);
            setCellValue(row, cellIndex++, flight.getChildTotalPrice(), priceStyle);
            setCellValue(row, cellIndex++, flight.getInfantPrice(), priceStyle);
            setCellValue(row, cellIndex++, flight.getInfantTax(), priceStyle);
            setCellValue(row, cellIndex++, flight.getInfantTotalPrice(), priceStyle);

            // 其他信息
            setCellValue(row, cellIndex++, flight.getCurrency(), dataStyle);
            setCellValue(row, cellIndex++, flight.getCabinClass(), dataStyle);
            setCellValue(row, cellIndex++, flight.getTransferCount(), dataStyle);
            setCellValue(row, cellIndex++, flight.getIsDirectFlight() ? "是" : "否", dataStyle);
            setCellValue(row, cellIndex++, flight.getBaggageInfo(), dataStyle);
            setCellValue(row, cellIndex++, flight.getMiseryIndex(), dataStyle);
            setCellValue(row, cellIndex++, flight.getTicketCount(), dataStyle);

            // 购买须知
            String purchaseNotes = flight.getPurchaseNotes() != null ?
                    String.join("; ", flight.getPurchaseNotes()) : "";
            setCellValue(row, cellIndex++, purchaseNotes, dataStyle);
        }
    }

    /**
     * 填充往返数据行
     */
    private void fillRoundTripDataRows(Sheet sheet, List<RoundTripFlightInfo> flights,
                                       CellStyle dataStyle, CellStyle priceStyle) {
        for (int i = 0; i < flights.size(); i++) {
            Row row = sheet.createRow(i + 1);
            RoundTripFlightInfo flight = flights.get(i);
            int cellIndex = 0;

            // 基础信息
            setCellValue(row, cellIndex++, flight.getRouteDescription(), dataStyle);
            setCellValue(row, cellIndex++, flight.getAdultTotalPrice(), priceStyle);
            setCellValue(row, cellIndex++, flight.getChildTotalPrice(), priceStyle);
            setCellValue(row, cellIndex++, flight.getInfantTotalPrice(), priceStyle);
            setCellValue(row, cellIndex++, flight.getCurrency(), dataStyle);
            setCellValue(row, cellIndex++, flight.getCabinClass(), dataStyle);
            setCellValue(row, cellIndex++, flight.getTotalTransferCount(), dataStyle);
            setCellValue(row, cellIndex++, flight.getIsAllDirectFlight() ? "是" : "否", dataStyle);
            setCellValue(row, cellIndex++, flight.getBaggageInfo(), dataStyle);
            setCellValue(row, cellIndex++, flight.getMiseryIndex(), dataStyle);
            setCellValue(row, cellIndex++, flight.getTicketCount(), dataStyle);

            // 去程信息
            OneWayFlightInfo outbound = flight.getOutboundFlight();
            if (outbound != null) {
                setCellValue(row, cellIndex++, outbound.getFlightNumber(), dataStyle);
                setCellValue(row, cellIndex++, outbound.getDepartureTime(), dataStyle);
                setCellValue(row, cellIndex++, outbound.getArrivalTime(), dataStyle);
                setCellValue(row, cellIndex++, outbound.getDuration(), dataStyle);
                setCellValue(row, cellIndex++, outbound.getTransferCount(), dataStyle);
                setCellValue(row, cellIndex++, outbound.getIsDirectFlight() ? "是" : "否", dataStyle);
                setCellValue(row, cellIndex++, outbound.getDepartureAirport(), dataStyle);
                setCellValue(row, cellIndex++, outbound.getArrivalAirport(), dataStyle);
                setCellValue(row, cellIndex++, outbound.getDepartureCity(), dataStyle);
                setCellValue(row, cellIndex++, outbound.getArrivalCity(), dataStyle);
            } else {
                // 如果去程为空，填充空值
                for (int j = 0; j < 10; j++) {
                    setCellValue(row, cellIndex++, "", dataStyle);
                }
            }

            // 返程信息
            OneWayFlightInfo returnFlight = flight.getReturnFlight();
            if (returnFlight != null) {
                setCellValue(row, cellIndex++, returnFlight.getFlightNumber(), dataStyle);
                setCellValue(row, cellIndex++, returnFlight.getDepartureTime(), dataStyle);
                setCellValue(row, cellIndex++, returnFlight.getArrivalTime(), dataStyle);
                setCellValue(row, cellIndex++, returnFlight.getDuration(), dataStyle);
                setCellValue(row, cellIndex++, returnFlight.getTransferCount(), dataStyle);
                setCellValue(row, cellIndex++, returnFlight.getIsDirectFlight() ? "是" : "否", dataStyle);
                setCellValue(row, cellIndex++, returnFlight.getDepartureAirport(), dataStyle);
                setCellValue(row, cellIndex++, returnFlight.getArrivalAirport(), dataStyle);
                setCellValue(row, cellIndex++, returnFlight.getDepartureCity(), dataStyle);
                setCellValue(row, cellIndex++, returnFlight.getArrivalCity(), dataStyle);
            } else {
                // 如果返程为空，填充空值
                for (int j = 0; j < 10; j++) {
                    setCellValue(row, cellIndex++, "", dataStyle);
                }
            }

            // 购买须知
            String purchaseNotes = flight.getPurchaseNotes() != null ?
                    String.join("; ", flight.getPurchaseNotes()) : "";
            setCellValue(row, cellIndex++, purchaseNotes, dataStyle);
        }
    }

    /**
     * 设置单元格值
     */
    private void setCellValue(Row row, int cellIndex, Object value, CellStyle style) {
        Cell cell = row.createCell(cellIndex);

        if (value == null) {
            cell.setCellValue("");
        } else if (value instanceof String) {
            cell.setCellValue((String) value);
        } else if (value instanceof Integer) {
            cell.setCellValue(((Integer) value).doubleValue());
        } else if (value instanceof BigDecimal) {
            cell.setCellValue(((BigDecimal) value).doubleValue());
        } else if (value instanceof Boolean) {
            cell.setCellValue((Boolean) value);
        } else {
            cell.setCellValue(value.toString());
        }

        cell.setCellStyle(style);
    }

    /**
     * 创建表头样式
     */
    private CellStyle createHeaderStyle(Workbook workbook) {
        CellStyle style = workbook.createCellStyle();
        style.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
        style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        style.setBorderTop(BorderStyle.THIN);
        style.setBorderBottom(BorderStyle.THIN);
        style.setBorderLeft(BorderStyle.THIN);
        style.setBorderRight(BorderStyle.THIN);

        Font font = workbook.createFont();
        font.setBold(true);
        style.setFont(font);

        return style;
    }

    /**
     * 创建数据样式
     */
    private CellStyle createDataStyle(Workbook workbook) {
        CellStyle style = workbook.createCellStyle();
        style.setBorderTop(BorderStyle.THIN);
        style.setBorderBottom(BorderStyle.THIN);
        style.setBorderLeft(BorderStyle.THIN);
        style.setBorderRight(BorderStyle.THIN);
        style.setWrapText(true);

        return style;
    }

    /**
     * 创建价格样式
     */
    private CellStyle createPriceStyle(Workbook workbook) {
        CellStyle style = createDataStyle(workbook);
        DataFormat dataFormat = workbook.createDataFormat();
        style.setDataFormat(dataFormat.getFormat("0.00"));

        return style;
    }

    /**
     * 调整单程列宽
     */
    private void adjustOneWayColumnWidths(Sheet sheet) {
        // 航班号
        sheet.setColumnWidth(0, 15 * 256);
        // 航空公司
        sheet.setColumnWidth(1, 15 * 256);
        // 时间列
        sheet.setColumnWidth(2, 20 * 256);
        sheet.setColumnWidth(3, 20 * 256);
        // 机场信息
        sheet.setColumnWidth(6, 20 * 256);
        sheet.setColumnWidth(7, 20 * 256);
        sheet.setColumnWidth(8, 15 * 256);
        sheet.setColumnWidth(9, 15 * 256);
        // 价格列
        for (int i = 12; i <= 20; i++) {
            sheet.setColumnWidth(i, 12 * 256);
        }
        // 行李额度
        sheet.setColumnWidth(25, 30 * 256);
        // 购买须知
        sheet.setColumnWidth(28, 40 * 256);
    }

    /**
     * 调整往返列宽
     */
    private void adjustRoundTripColumnWidths(Sheet sheet) {
        // 路线描述
        sheet.setColumnWidth(0, 20 * 256);
        // 价格列
        for (int i = 1; i <= 3; i++) {
            sheet.setColumnWidth(i, 12 * 256);
        }
        // 航班号列
        sheet.setColumnWidth(11, 20 * 256);
        sheet.setColumnWidth(21, 20 * 256);
        // 时间列
        sheet.setColumnWidth(12, 20 * 256);
        sheet.setColumnWidth(13, 20 * 256);
        sheet.setColumnWidth(22, 20 * 256);
        sheet.setColumnWidth(23, 20 * 256);
        // 机场信息
        for (int i = 17; i <= 20; i++) {
            sheet.setColumnWidth(i, 18 * 256);
        }
        for (int i = 27; i <= 30; i++) {
            sheet.setColumnWidth(i, 18 * 256);
        }
        // 购买须知
        sheet.setColumnWidth(31, 40 * 256);
    }
}
